import { baseBody } from "../body/baseBody";
import SK_func from "../skill/SK_func";
import { battle_log, SKILL } from "../skill/SK_active";
import { bar, group, round_log } from "../../../shared/interface";
import { player } from "../body/player";
import { Tpl_battleLog, template } from "../../../shared/master/MsgAction";
import app from "../../../app";
import { logger } from "../../server/logger";
import { calls } from "../body/calls";
import { enemy } from "../body/enemy";
import god from "../../../god";


export default class battlefield {
    id: string = app.v4()
    round: number = 0;
    active: boolean = false;
    private _logs: battle_log[] = [];
    /**
     * 用于记录每回合击杀  和获得奖励
     */
    private _roundLog: Map<string, round_log> = new Map();
    // new battle list
    groupList: Map<string, baseBody>[] = [];
    timerId: NodeJS.Timeout | undefined;
    private _lisentBattleEndCall: any;
    private _lisentBattleOutEnd: any;
    private _lisentBattleKill: any;
    private _lisentBattleRound: any;
    /**
     * 是否为特殊战  特殊战一旦发起 其他单位无法参与进来
     */
    private special: boolean = false;

    /**
     * 用于记录本回合 相同名字不同UUID的数量
     */
    private nameContMap: Map<string, any> = new Map();
    private roundTime: number = 10;
    constructor() {
        this.roundTime = Number(god.getServerCfgItem('battle_roundTime').a)
        this.groupList = [new Map(), new Map()];
    }
    addRoundLog(id: string, a: string, b: string, items: { name: string, cont: number }[]) {
        let data: round_log;
        if (this._roundLog.has(`${a}_${b}`)) {
            data = this._roundLog.get(`${a}_${b}`) as round_log
        } else {
            data = {
                logs: [],
                items: []
            }
        }

        // 遍历新的items数组
        for (const newItem of items) {
            let foundItem = false;
            // 遍历已存在的items数组
            for (let i = 0; i < data.items.length && !foundItem; i++) {
                const existingItem = data.items[i];
                if (existingItem.name === newItem.name) {
                    // 如果找到同名项，则将数量相加
                    existingItem.cont += newItem.cont;
                    foundItem = true;
                }
            }
            // 如果新的items中没有找到同名项，则将其添加到items数组中
            if (!foundItem) {
                data.items.push(newItem);
            }
        }

        data.logs.push({
            a_name: a,
            b_name: b,
        });

        this._roundLog.set(id, data);
    }
    getRoundTime() {
        return this.roundTime;
    }
    setRoundTime(n: number) {
        this.roundTime = n;
    }
    /**
     * 设置战斗是否为特殊战
     */
    setSpecial(b: boolean) {
        this.special = b;
    }
    checkSpecial() {
        return this.special
    }
    setRoundCall(call: any) {
        this._lisentBattleRound = call;
    }
    setKillCall(call: any) {
        this._lisentBattleKill = call;
    }
    setEndCall(call: any) {
        this._lisentBattleEndCall = call;
    }
    setOutEndCall(call: any) {
        this._lisentBattleOutEnd = call;
    }
    addKillLog(active: baseBody, die: baseBody, sk: SKILL) {
        this._lisentBattleKill(this, active, die, sk)
    }
    addLog(log: battle_log) {
        if (!this.nameContMap.has(`${log.use_name}_${log.group}`)) {
            this.nameContMap.set(`${log.use_name}_${log.group}`, { [log.use_uuid]: 1 })
        } else {
            const obj = this.nameContMap.get(`${log.use_name}_${log.group}`);
            if (!obj[log.use_uuid]) {
                obj[log.use_uuid] = 1;
                this.nameContMap.set(log.use_name, obj)
            }
        }
        if (typeof (log.val) == 'string') {
            this._logs.push(log);
            return;
        }



        const index = this._logs.findIndex((item) => item.use_name === log.use_name && item.type === log.type && item.group == log.group && item.sk_name == log.sk_name);
        if (index >= 0) {
            (this._logs[index].val as number) += log.val;
        } else {
            this._logs.push(log);
        }
    }
    clearAllLog() {
        this._logs = [];
        this._roundLog.clear();
        this.nameContMap.clear();
    }
    nextRound() {
        this.clearAllLog();
        this.round += 1;
        // console.clear()
    }
    join(body: baseBody, group: group) {
        let joins = [body];
        let pets = body.getPets()
        for (let i = 0; i < pets.length; i++) {
            const element = pets[i];
            joins.push(element)
        }

        for (let i = 0; i < joins.length; i++) {
            const element = joins[i];
            if (element.is_die()) {
                console.error('单位已死亡，无法加入战斗');
                return;
            }
            element.set_group(group);
            element.set_battle(this);
            console.log(`${element.name}加入战斗`);
            try {
                this.groupList[group].set(element.uuid, element);
            } catch (error) {
                debugger;
            }
        }


    }
    out(body: baseBody) {
        let outBodys: baseBody[] = []
        let outs = this.getBody_all();
        for (let i = 0; i < outs.length; i++) {
            const element = outs[i];
            if (element.uuid == body.uuid) {
                outBodys.push(element);
                continue;
            }
            if (element.get_Master().uuid == body.uuid) {
                outBodys.push(element);
                continue;
            }
        }
        for (let i = 0; i < outBodys.length; i++) {
            const element = outBodys[i];
            element.del_battle();
            this.groupList[group.主场].delete(element.uuid) || this.groupList[group.客场].delete(element.uuid)
            if (this.groupList[group.主场].size == 0 || this.groupList[group.客场].size == 0) {
                logger.debug(`${element.name}退出战场,战斗结束`)
                this.end();
                this._lisentBattleOutEnd(this, body);
            }
        }

    }
    end() {
        clearTimeout(this.timerId); // 取消计时器
        this.active = false;
    }
    start() {
        if (!this.active) {
            this.tick_bf();
        }
        this.active = true;
    }
    getBody_all_group(g: group) {
        return [...this.groupList[g].values()]
    }
    getBody_all() {
        return [...this.groupList[group.主场].values(), ...this.groupList[group.客场].values()]
    }
    getBody(uuid: string) {
        return this.groupList[group.主场].get(uuid) || this.groupList[group.客场].get(uuid)
    }
    /**
     * 通知玩家进行决策
     */
    notice_battleSelect(maps: Map<string, baseBody>) {
        maps.forEach(element => {
            if (element instanceof player) {
                element.on_battleSelect()
                console.log(`正在通知${element.name}进行决策`);
            } else {
                element.set_hasDecided(this.round);
                this.on_battleSelect(element);
            }
        });
    }
    on_battleSelect(body: baseBody) {

        let activeGroup = [...this.groupList[group.主场].values(), ...this.groupList[group.客场].values()];
        // get_hasDecided
        let hasAllDice = true;
        for (let index = 0; index < activeGroup.length; index++) {
            const element = activeGroup[index];
            if (element.get_hasDecided() != this.round) {
                hasAllDice = false;
                break;
            }
        }
        // 已经全部做完决策,开始执行战斗逻辑
        if (hasAllDice) {
            console.info('已经全部做完决策')
            clearTimeout(this.timerId); // 取消计时器
            this.tick();
        }
    }
    tick_bf() {
        if (!this.groupList) {
            console.error('---------')
        }
        for (let index = 0; index < this.groupList.length; index++) {
            const activeGroup = this.groupList[index];
            this.notice_battleSelect(activeGroup);
        }

        this.timerId = setTimeout(() => { // 存储计时器 ID
            console.log('超时');
            this.tick();
        }, this.roundTime * 1000);

    }

    async tick() {
        if (!this.active) {
            return;
        }
        this.nextRound();
        let end = -1;
        let callBody: Map<string, player> = new Map();
        let _bar: bar[] = [{ num: 0, now: 0, max: 0 }, { num: 0, now: 0, max: 0 }]
        for (let index = 0; index < this.groupList.length; index++) {
            let allDie = true;
            const activeGroup = app.shuffleArray(this.groupList[index]);
            activeGroup.forEach(element => {
                if (element instanceof player) {
                    callBody.set(element.uuid, element)
                }
                if (!element || element.is_die()) {
                    console.log('单位已死亡')
                    return;
                }
                element.active();
                console.log(`${element.name}开始攻击`)
                SK_func.skill_use(this, element)
                if (!element.is_die()) {
                    allDie = false;
                }
                _bar[index].max += element._attributes.Hp_Max;
                _bar[index].now += element.Hp_now;
            });
            if (allDie) {
                end = index;
                console.log('一方单位全部死亡,失败方', index);
                this.end();
                // 战斗结束
                break;
            }
        }
        if (end == -1) {
            _bar = [{ num: 0, now: 0, max: 0 }, { num: 0, now: 0, max: 0 }]
            // 再检测一次是否全部死亡
            for (let index = 0; index < this.groupList.length; index++) {
                let allDie = true;
                const activeGroup = [...this.groupList[index].values()];
                for (let i = 0; i < activeGroup.length; i++) {
                    const element = activeGroup[i];
                    if (!element.is_die()) {
                        allDie = false;
                        _bar[index].max += element._attributes.Hp_Max;
                        _bar[index].now += element.Hp_now;
                        break;
                    }
                }
                if (allDie) {
                    end = index;
                    console.log('复盘检测:一方单位全部死亡,失败方', index);
                    this.end();
                    // 战斗结束
                    break;
                }
            }
        }
        // let callBody = [...this.groupList[0].values(), ...this.groupList[1].values()];

        // 通知对应单位回合log
        this._roundLog.forEach((element, key) => {
            let body = callBody.get(key)
            if (!body) {
                return;
            }
            body.sendMsg(template.Battle_round, element)
        });

        _bar[0].num = _bar[0].now / _bar[0].max
        _bar[1].num = _bar[1].now / _bar[1].max
        let log: Tpl_battleLog = {
            word_name: "",
            x: 0,
            y: 0,
            logs: this._logs,
            census: _bar
        }

        if (this._logs.length > 0) {
            for (let index = 0; index < this._logs.length; index++) {
                const element = this._logs[index];
                const nameObj = this.nameContMap.get(`${element.use_name}_${element.group}`)
                try {
                    const objLeng = Object.keys(nameObj).length;
                    if (objLeng > 1) {
                        this._logs[index].use_name += `X${objLeng}`
                    }
                } catch (error) {
                    debugger
                }

            }
            console.log(`日志通知单位:`, callBody)
        }
        if (end != -1) {
            let windGroup = end == group.主场 ? group.客场 : group.主场;
            this._lisentBattleEndCall(this, windGroup, log);
            return;
        } else {
            callBody.forEach(element => {
                element.sendMsg(template.Battle_log, log)
            });
        }

        this._lisentBattleRound && this._lisentBattleRound(this, this.groupList);
        try {
            this.tick_bf();
        } catch (error) {
            debugger
        }
    }
    destroy() {
        // if (this.special) {
        //     logger.debug('特殊战 不自动销毁')
        //     return;
        // }
        logger.debug(`[info]战场销毁`)
        let bodys = this.getBody_all()
        bodys.forEach(element => {
            element.del_battle();
            if (element instanceof calls) {
                element.destroy();
            }
            if (element instanceof enemy && element.is_die()) {
                element.destroy();
            }
        });
        clearTimeout(this.timerId); // 取消计时器

        setTimeout(() => {
            for (const key in this) {
                (this[key] as any) = undefined;
            }
        }, 1000)

    }
}